package com.riteny.paymentgateway.swifypass.common;

import com.riteny.paymentgateway.swifypass.exception.SwiftPassPaymentGatewayException;
import net.sf.json.JSONObject;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @author Riteny
 * 2021/5/25  14:49
 */
public class SwiftPassPaymentGatewaySha256Util {


    public static String getSignStr(Element element, String key) {
        //step2 將XML按照字母順序進行排序，主要方便驗簽時使用
        SortedMap<String, String> map = xmlToMap(element);

        //step3 去掉無效字段
        Map<String, String> params = paraFilter(map);

        //step4 獲取待簽名字串
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SwiftPassPaymentGatewaySignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();

        //step5 對參數字符串進行簽名

        return SwiftPassPaymentGatewaySha256Util.getSHA256(preStr + "&key=" + key).toUpperCase();
    }

    public static Element checkSignStrFromResponse(String responseStr, String key) {

        try {
            Document document = DocumentHelper.parseText(responseStr);

            Element responseXml = document.getRootElement();

            if (!"0".equals(responseXml.elementText("status"))) {
                throw new SwiftPassPaymentGatewayException(responseXml.elementText("status"), responseXml.elementText("message"));
            }

            String signForResponse = responseXml.elementText("sign");

            String currentSign = getSignStr(responseXml, key);

            if (!signForResponse.equals(currentSign)) {
                throw new SwiftPassPaymentGatewayException(SwiftPassPaymentGatewayException.UNKNOWN_ERROR, "Signature error");
            }

            return responseXml;
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static String getSignStr(JSONObject element, String key) {
        //step2 將XML按照字母順序進行排序，主要方便驗簽時使用
        SortedMap<String, String> map = new TreeMap<>(element);

        //step3 去掉無效字段
        Map<String, String> params = paraFilter(map);

        //step4 獲取待簽名字串
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SwiftPassPaymentGatewaySignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();

        //step5 對參數字符串進行簽名

        return SwiftPassPaymentGatewaySha256Util.getSHA256(preStr + "&key=" + key).toUpperCase();
    }

    public static JSONObject checkSignStr(JSONObject responseJson, String key) {

        String signForResponse = responseJson.optString("sign");

        String currentSign = getSignStr(responseJson, key);

        if (!signForResponse.equals(currentSign)) {
            throw new SwiftPassPaymentGatewayException(SwiftPassPaymentGatewayException.UNKNOWN_ERROR, "Signature error");
        }

        return responseJson;
    }


    private static SortedMap<String, String> xmlToMap(Element element) {

        SortedMap<String, String> map = new TreeMap<>();

        List<Element> elements = element.elements();

        elements.forEach(element1 -> {
            map.put(element1.getName(), element1.getText());
        });

        return map;
    }

    private static Map<String, String> paraFilter(Map<String, String> sArray) {
        Map<String, String> result = new HashMap<>(sArray.size());
        if (sArray == null || sArray.size() <= 0) {
            return result;
        }
        for (String key : sArray.keySet()) {
            Object obj = sArray.get(key);

            String value = obj != null ? String.valueOf(obj) : "";
            if (value == null || value.equals("") || key.equalsIgnoreCase("sign")) {
                continue;
            }
            result.put(key, value);
        }
        return result;
    }


    /**
     * 利用java原生的类实现SHA256加密
     *
     * @param str 参数拼接的字符串
     * @return
     */
    public static String getSHA256(String str) {
        MessageDigest messageDigest;
        String encodeStr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes("UTF-8"));
            encodeStr = byte2Hex(messageDigest.digest());
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encodeStr;
    }

    /**
     * 将byte转为16进制
     *
     * @param bytes
     * @return
     */
    private static String byte2Hex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        String temp = null;
        for (byte aByte : bytes) {
            temp = Integer.toHexString(aByte & 0xFF);
            if (temp.length() == 1) {
                // 1得到一位的进行补0操作
                sb.append("0");
            }
            sb.append(temp);
        }
        return sb.toString();
    }
}
